package cn.tedu.charging.device.service.impl;

import cn.tedu.charging.common.pojo.query.NearStationsQuery;
import cn.tedu.charging.common.pojo.vo.GunInfoVO;
import cn.tedu.charging.common.pojo.vo.StationDetailVO;
import cn.tedu.charging.common.pojo.vo.StationInfoVO;
import cn.tedu.charging.device.dao.repository.DeviceRepository;
import cn.tedu.charging.device.pojo.po.ChargingGunInfoPO;
import cn.tedu.charging.device.pojo.po.ChargingStationPO;
import cn.tedu.charging.device.pojo.po.StationGeoPO;
import cn.tedu.charging.device.service.DeviceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    private DeviceRepository deviceRepository;
    @Override
    public void startOnceWarmUp() {
        //1.读取判断缓存是否存在
        Boolean exists=deviceRepository.geoStationsExists();
        //判断不存在
        if (!exists){
            log.debug("缓存预热未执行,开始执行预热实现");
            //2.读取全量数据数字 定义批量数字
            Long total=deviceRepository.countAll();
            Long batch=1000l;
            //3.计算循环次数
            Long loopSize=total%batch==0?total/batch:total/batch+1;
            //4.循环
            for (Long i=0l;i<loopSize;i++){
                log.debug("循环批量数据,第{}次",i+1);
                //5.读取本批次数据
                Long start=batch*i;
                Long rows=batch;
                List<ChargingStationPO> pos=deviceRepository.getStationsPage(start,rows);
                //6.调用写入geo
                deviceRepository.saveGeos(pos);
            }
        }else{
            log.debug("缓存预热已执行,数据避免冲突,停止");
        }
    }

    /**
     * 一次性预热实现
     */
    /*@Override
    public void startOnceWarmUp() {
        //1.读取所有的station数据
        List<ChargingStationPO> pos=deviceRepository.getStations();
        //判断非空
        if (pos!=null&&pos.size()>0) {
            //2.写入redis charging:stations:all
            deviceRepository.saveGeos(pos);
        }
    }*/
    @Override
    public List<StationInfoVO> nearStations(NearStationsQuery query) {
        List<StationInfoVO> vos=null;
        //1.读取仓储层的数据集合
        List<StationGeoPO> geoPos=deviceRepository.nearStations(query);
        //判断非空
        if (geoPos!=null&&geoPos.size()>0){
            log.debug("查询到了{}个场站",geoPos.size());
            vos=geoPos.stream().map(po->{
                StationInfoVO vo=new StationInfoVO();
                BeanUtils.copyProperties(po,vo);
                vo.setAvgPrice(calculateAvgPrice(po.getStationId()));
                return vo;
            }).collect(Collectors.toList());
        }else{
            log.debug("没有命中任何场站数据");
        }
        //3.排序 将vo对象中距离越小的排序越靠前 stream().sorted()
        vos=vos.stream().sorted((vo1,vo2)->{
            return vo1.getDistance().compareTo(vo2.getDistance());
        }).collect(Collectors.toList());
        return vos;
    }

    private Double calculateAvgPrice(Integer stationId) {
        //实际计算可能要耗费多个服务和数据平台资源--轻做
        return 1.55;
    }

    /**
     * 打印debug日志级别的规范
     * debug调试日志级别 关注方法程序执行的重要参数变量,以及流程(分支),以及状态
     * 1. 方法入口和方法出口
     */
    @Override
    public StationDetailVO detailStation(Integer stationId) {
        log.debug("查询场站信息详情实现,入参stationId:{}",stationId);
        //准备一个返回值
        StationDetailVO vo=null;
        //1.调用仓储层查询对一个id持久化对象
        ChargingStationPO stationPO = deviceRepository.getStationById(stationId);
        //判断是否是空
        if(stationPO!=null){
            log.debug("查询场站信息详情实现,命中stationPO:{}",stationPO);
            //场站非空,封装vo属性 4个属性来自stationPO stationId stationStatus stationName address
            vo=new StationDetailVO();
            BeanUtils.copyProperties(stationPO,vo);
            vo.setStationId(stationId);
            //2.场站非空,利用场站id查询对应枪列表
            List<ChargingGunInfoPO> gunPos=deviceRepository.getStationGuns(stationId);
            //判断非空
            if (gunPos!=null&&gunPos.size()>0){
                log.debug("查询场站信息详情实现,场站关联枪,gunPos:{}",gunPos);
                //3.转化 gunPos转化映射成gunVos
                List<GunInfoVO> gunVos=gunPos.stream().map(gunPo->{
                    //准备一个GunInfoVO 从GunPO拷贝数据
                    GunInfoVO gunVo=new GunInfoVO();
                    BeanUtils.copyProperties(gunPo,gunVo);
                    return gunVo;
                }).collect(Collectors.toList());
                //封装stationDetailvo最后一个属性
                vo.setGunInfoVos(gunVos);
            }else{
                log.debug("查询场站信息详情实现,场站关联枪,gunPos:null");
            }
        }else {
            log.debug("查询场站信息详情实现,未命中stationPO:null");
        }
        return vo;
    }

    @Override
    public void updateGunStatus(Integer gunId, Integer status) {

    }

    @Override
    public Boolean checkGunAvailable(Integer gunId) {
        return null;
    }



}
